package xyz.zcq.zcqrpc.loadbalancer;

import cn.hutool.core.collection.CollectionUtil;
import xyz.zcq.zcqrpc.model.ServiceMetaInfo;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * 一致性hash负载均衡器
 */
public class ConsistentHashLoadBalancer implements LoadBalancer {

    /**
     * hash环的节点map
     */
    private final TreeMap<Integer, ServiceMetaInfo> nodesMap = new TreeMap<>();
    /**
     * 单个服务的节点数
     */
    private static final int VIRTUAL_NODE_NUM = 100;

    @Override
    public ServiceMetaInfo select(Map<String, Object> requestParam, List<ServiceMetaInfo> serviceMetaInfoList) {
        if (CollectionUtil.isEmpty(serviceMetaInfoList)) {
            return null;
        }
        int size = serviceMetaInfoList.size();
        if (size == 1) {
            return serviceMetaInfoList.get(0);
        }

        for (ServiceMetaInfo serviceMetaInfo : serviceMetaInfoList) {
            for (int i = 0; i < VIRTUAL_NODE_NUM; i++) {
                int hash = getHash(serviceMetaInfo.getServiceAddress() + "#" + i);
                nodesMap.put(hash, serviceMetaInfo);
            }
        }

        Map.Entry<Integer, ServiceMetaInfo> entry = nodesMap.ceilingEntry(getHash(requestParam));
        if (entry == null) {
            entry = nodesMap.firstEntry();
        }

        return entry.getValue();
    }

    /**
     * hash算法
     *
     * @param o 要获取hash值的对象
     * @return hash值
     */
    private int getHash(Object o) {
        return o.hashCode();
    }

}
